package voxelTest;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import javax.swing.JFrame;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;

public class BasicRenderer {
    DisplayMode displayMode;
    private int cubesWidth = GC.MAZE_WIDTH*2-1;
    private int cubesHeight = GC.MAZE_HEIGHT*2-1;
	private float PY = cubesHeight;
	private float PX = -cubesWidth;
	private float PZ = -Math.max(PX, PY);
	private float RX = 0;
	private float RY = 20;
	private float RZ = 0;

	private int xsquares = 1;
	private int ysquares = 1;
	private JFrame g;
	private Maze maze;
	private boolean[][] map;
	private boolean[][] buffMap;
	
	public BasicRenderer(int xsquares, int ysquares) {
		maze = new Maze(xsquares,ysquares);
		this.buffMap = new boolean[xsquares*2-1][ysquares*2-1];
		this.xsquares = xsquares*2-1;
		this.ysquares = ysquares*2-1;

		
		//this.maze.start();
		(new Thread(this.maze)).start();
		//maze.run();

		System.out.println("Hola");
	}
	
	public void Start(){
		 try {
		 createWindow();
		 InitGL();
		 Run();
		 } catch (Exception e) {	 
			 e.printStackTrace();
		 }
	 }
	 
    private void createWindow() throws Exception {
         Display.setFullscreen(false);
         DisplayMode d[] = Display.getAvailableDisplayModes();
         for (int i = 0; i < d.length; i++) {
             if (d[i].getWidth() == 800
                 && d[i].getHeight() == 600
                 && d[i].getBitsPerPixel() == 32) {
                 displayMode = d[i];
                 break;
             }
         }
         Display.setDisplayMode(displayMode);
         Display.setTitle("LWJGL Voxel engine");
         Display.create();
     }
    private void InitGL() {
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glShadeModel(GL11.GL_SMOOTH);
        GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
        GL11.glClearDepth(1.0); 
        GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glDepthFunc(GL11.GL_LEQUAL); 

        GL11.glMatrixMode(GL11.GL_PROJECTION); 
        GL11.glLoadIdentity();

        
        GLU.gluPerspective(
          100.0f,
          (float)displayMode.getWidth()/(float)displayMode.getHeight(),
          0.1f,
          1000.0f);

        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
    }
    private void Run() {
    	 while (!Display.isCloseRequested()) {
    	 try{
    	 Render();
         Display.update();
    	 Display.sync(60);
    	 }catch(Exception e){
    	 
    	 }
    	 }
    	 Display.destroy();
    	 }
    public void RenderCube(Float Red, Float Green, Float Blue) {
    	 GL11.glBegin(GL11.GL_QUADS);
    	 GL11.glColor3f(Red, Green, Blue);
    	 GL11.glVertex3f(1.0f, 1.0f, -1.0f);
    	 GL11.glVertex3f(-1.0f, 1.0f, -1.0f);
    	 GL11.glVertex3f(-1.0f, 1.0f, 1.0f);
    	 GL11.glVertex3f(1.0f, 1.0f, 1.0f);
    	 GL11.glVertex3f(1.0f, -1.0f, 1.0f);
    	 GL11.glVertex3f(-1.0f, -1.0f, 1.0f);
    	 GL11.glVertex3f(-1.0f, -1.0f, -1.0f);
    	 GL11.glVertex3f(1.0f, -1.0f, -1.0f); 
    	 GL11.glVertex3f(1.0f, 1.0f, 1.0f); 
    	 GL11.glVertex3f(-1.0f, 1.0f, 1.0f); 
    	 GL11.glVertex3f(-1.0f, -1.0f, 1.0f); 
    	 GL11.glVertex3f(1.0f, -1.0f, 1.0f);
    	 GL11.glVertex3f(1.0f, -1.0f, -1.0f); 
    	 GL11.glVertex3f(-1.0f, -1.0f, -1.0f);
    	 GL11.glVertex3f(-1.0f, 1.0f, -1.0f);
    	 GL11.glVertex3f(1.0f, 1.0f, -1.0f);
    	 GL11.glVertex3f(-1.0f, 1.0f, 1.0f);
    	 GL11.glVertex3f(-1.0f, 1.0f, -1.0f);
    	 GL11.glVertex3f(-1.0f, -1.0f, -1.0f);
    	 GL11.glVertex3f(-1.0f, -1.0f, 1.0f); 
    	 GL11.glVertex3f(1.0f, 1.0f, -1.0f);
    	 GL11.glVertex3f(1.0f, 1.0f, 1.0f);
    	 GL11.glVertex3f(1.0f, -1.0f, 1.0f); 
    	 GL11.glVertex3f(1.0f, -1.0f, -1.0f);
    	 GL11.glEnd();
    	 
    	 GL11.glColor3f(Red/2, Green/2, Blue/2);
    	 GL11.glBegin(GL11.GL_LINE_STRIP);
    	 GL11.glVertex3f(1.0f, 1.0f, -1.0f);
    	 GL11.glVertex3f(-1.0f, 1.0f, -1.0f);
    	 GL11.glVertex3f(-1.0f, 1.0f, 1.0f);
    	 GL11.glVertex3f(1.0f, 1.0f, 1.0f);
    	 GL11.glEnd();
    	 GL11.glBegin(GL11.GL_LINE_STRIP);
    	 GL11.glVertex3f(1.0f, -1.0f, 1.0f);
    	 GL11.glVertex3f(-1.0f, -1.0f, 1.0f);
    	 GL11.glVertex3f(-1.0f, -1.0f, -1.0f);
    	 GL11.glVertex3f(1.0f, -1.0f, -1.0f); 
    	 GL11.glEnd();
    	 GL11.glBegin(GL11.GL_LINE_STRIP);
    	 GL11.glVertex3f(1.0f, 1.0f, 1.0f); 
    	 GL11.glVertex3f(-1.0f, 1.0f, 1.0f); 
    	 GL11.glVertex3f(-1.0f, -1.0f, 1.0f); 
    	 GL11.glVertex3f(1.0f, -1.0f, 1.0f);
    	 GL11.glEnd();
    	 GL11.glBegin(GL11.GL_LINE_STRIP);
    	 GL11.glVertex3f(1.0f, -1.0f, -1.0f); 
    	 GL11.glVertex3f(-1.0f, -1.0f, -1.0f);
    	 GL11.glVertex3f(-1.0f, 1.0f, -1.0f);
    	 GL11.glVertex3f(1.0f, 1.0f, -1.0f);
    	 GL11.glEnd();
    	 GL11.glBegin(GL11.GL_LINE_STRIP);
    	 GL11.glVertex3f(-1.0f, 1.0f, 1.0f);
    	 GL11.glVertex3f(-1.0f, 1.0f, -1.0f);
    	 GL11.glVertex3f(-1.0f, -1.0f, -1.0f);
    	 GL11.glVertex3f(-1.0f, -1.0f, 1.0f);
    	 GL11.glEnd();
    	 GL11.glBegin(GL11.GL_LINE_STRIP);
    	 GL11.glVertex3f(1.0f, 1.0f, -1.0f);
    	 GL11.glVertex3f(1.0f, 1.0f, 1.0f);
    	 GL11.glVertex3f(1.0f, -1.0f, 1.0f); 
    	 GL11.glVertex3f(1.0f, -1.0f, -1.0f);
    	 GL11.glEnd();
    	 }
    private void Render() {
    	ProcessInput();
		if(GC.RESTART) {
			this.maze.end();
			this.xsquares = GC.MAZE_WIDTH*2-1;
			this.ysquares = GC.MAZE_HEIGHT*2-1;
			this.maze = new Maze(GC.MAZE_WIDTH,GC.MAZE_HEIGHT);
			this.maze.start();
			GC.RESTART = false;
			this.buffMap = new boolean[xsquares][ysquares];
		}
		
		this.map = maze.getMap();

		
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
		GL11.glLoadIdentity();
		GL11.glTranslatef(PX, PY, PZ);
		
		GL11.glRotatef(90f, 1.0f, 0f, 0f);
		GL11.glRotatef(90f, 0f, 0f, -1.0f);
		GL11.glRotatef(-RY, 0, 1, 0);
		GL11.glRotatef(-RX, 1, 0, 0);
		GL11.glRotatef(-RZ, 0, 0, 1);
		GL11.glTranslatef(0, -this.cubesWidth, -this.cubesHeight);
		

		

		for (int i = 0; i < this.xsquares; i++) {
			for (int j = 0; j < this.ysquares; j++) {
				if (this.map[i][j]) {
					if (GC.PRINT_NEW) {
						if (this.buffMap[i][j]) {
							this.RenderCube(0.2f,0.8f,0.2f);
						}
						else {
							this.RenderCube(0.8f, 0.2f, 0.2f);		
						}
					}
					if (!GC.PAUSE) {
						this.buffMap[i][j] = true;
					}
				}
				GL11.glTranslatef(0f, 0.0f, 2f);
			}
			GL11.glTranslatef(0f, 2f, -2*this.cubesHeight);
		}
		GL11.glTranslatef(0f, -2*this.cubesWidth,0);
		
		ArrayList<Point> list = maze.getStack();
		if (GC.PRINT_STACK) {
			for (int i = 0; i < list.size(); i++) {
				try {
					Point p = list.get(i);
					if (p != null) {	
						GL11.glTranslatef(0, p.getX()*2, p.getY()*2);
						this.RenderCube(0.5f, 0.5f, 0.5f);
						GL11.glTranslatef(0, -p.getX()*2, -p.getY()*2);
					}
				} catch (Exception e) {
					System.err.println("Unsynchronized Thread caused null reference");
				}
			}
		}
		
		
		if (GC.PRINT_LEADER) {
			if (list.size()>0) {
				try {
					Point p = list.get(list.size()-1);
					if (p != null) {
						GL11.glTranslatef(0, p.getX()*2, p.getY()*2);
						this.RenderCube(0.9f, 0.9f, 0.1f);
						GL11.glTranslatef(0, -p.getX()*2, -p.getY()*2);
					}
				} catch (Exception e) {
					System.err.println("Unsynchronized Thread caused null reference");
				}
			}
		}
		
		
		/*if (GC.PRINT_STATUS) {
			g.setColor(Color.ORANGE);
			g.getFont().deriveFont(Font.BOLD);
			int inc = 16;
			g.drawString(maze.getStackStatus(), 2, 12);
			g.drawString(maze.getVisitedPlacesStatus(), 2, 12+inc);
			g.drawString(maze.getPlacesLeftStatus(), 2, 12+2*inc);
			g.drawString(maze.getColisionesStatus(), 2, 12+3*inc);
			g.drawString(maze.getElapsedTime(), 2, 12+inc*4);
			g.drawString(maze.getCurrentPointData(),2,12+inc*5);
			String a = "";
			if (GC.PAUSE){
				a = " (Paused)";
			}
			g.drawString("Speed: " + GC.MAZE_SLOWNESS + a, 2, 12+inc*6);

		}
		//g2.fillRoundRect(20, 20, 400, 400, 10, 10);

		//this.printSimpleString(maze.getStatus(), 0, 0, 10, (Graphics2D) g);
		
		/*for(int x = 0; x < this.cubesWidth; x++){
			for(int y = 0; y < this.cubesHeight; y++){
				RenderCube();
				GL11.glTranslatef(0f, 0.0f, 2f);
			}
			GL11.glTranslatef(0f, 2f, -2*this.cubesWidth);
		}  */
		
    }
 
	private void ProcessInput() {
		if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
			PY--;
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
			PY++;
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
			PX++;
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
			PX--;
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_E)) {
			PZ--;
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_Q)) {
			PZ++;
		}

		/*if (Keyboard.isKeyDown(Keyboard.KEY_G)) {
			RX--;
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_J)) {
			RX++;
		}*/
		if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
			RX++;
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
			RX--;
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
			RY--;
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
			RY++;
		}
	}







}
